package com.wms.db.dao.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.wms.db.dao.IBeanDao;


@SuppressWarnings("unchecked") 
public class BeanDao<T extends Serializable, PK extends Serializable> extends HibernateDaoSupport implements IBeanDao<T, PK> { 
    
    private Class<T> entityClass; 

    public BeanDao() { 
        this.entityClass = null; 
        Class c = getClass(); 
        Type t = c.getGenericSuperclass(); 
        if (t instanceof ParameterizedType) { 
            Type[] p = ((ParameterizedType) t).getActualTypeArguments(); 
            this.entityClass = (Class<T>) p[0]; 
        } 
    } 
    
    // Get object by id. If not find, return null. 
    public T get(PK id) { 
        return (T) getHibernateTemplate().get(entityClass, id); 
    } 

    // Get object by id. If not find, throw exception. 
    public T load(PK id) { 
        return (T) getHibernateTemplate().load(entityClass, id); 
    } 

    // get all
    public List<T> loadAll() { 
        return (List<T>) getHibernateTemplate().loadAll(entityClass); 
    } 

    // update
    public void update(T entity) { 
        getHibernateTemplate().update(entity); 
    } 

    // add
    public void save(T entity) { 
        getHibernateTemplate().save(entity); 
    } 

    // add or update
    public void saveOrUpdate(T entity) { 
        getHibernateTemplate().saveOrUpdate(entity); 
    } 
    
    // merge
    public void merge(T entity) { 
        getHibernateTemplate().merge(entity); 
    }

    // add or update all
    public void saveOrUpdateAll(Collection<T> entities) { 
        getHibernateTemplate().saveOrUpdateAll(entities); 
    } 

    // delete
    public void delete(T entity) { 
        getHibernateTemplate().delete(entity); 
    } 

    // delete By key
    public void deleteByKey(PK id) { 
        this.delete(this.load(id)); 
    } 

    // delete all
    public void deleteAll(Collection<T> entities) { 
        getHibernateTemplate().deleteAll(entities); 
    } 
       
    // -------------------------------- Criteria ------------------------------
    
    protected Criteria createCriteria() { 
        return DetachedCriteria.forClass(this.entityClass).getExecutableCriteria(this.getSession()); 
    } 
    
    public DetachedCriteria createDetachedCriteria() {  
        return DetachedCriteria.forClass(this.entityClass);  
    }  
    
    public Object getAggregateValue(DetachedCriteria criteria) {  
        return this.findByCriteria(criteria, 0, 1).get(0); 
    }  
  
    public Long getRowCountByCriteria(DetachedCriteria criteria) {  
        criteria.setProjection(Projections.rowCount());  
        return new Long((this.findByCriteria(criteria, 0, 1).get(0)).toString());  
    } 
    
    public List<T> findByCriteria(DetachedCriteria criteria) {  
        return this.getHibernateTemplate().findByCriteria(criteria);  
    }  
    
    public List<T> findByCriteria(DetachedCriteria criteria, Integer firstResult, Integer maxResults) {  
        return this.getHibernateTemplate().findByCriteria(criteria,firstResult, maxResults);  
    }   

} 